import { inject, injectable } from "inversify";
import { IExtensionSingleActivationService } from "../../activation/types";
import { IInterpreterDisplay, IInterpreterHelper, IInterpreterService, IInterpreterStatusbarVisibilityFilter } from "../contracts";
import * as nls from 'vscode-nls';
import { Disposable, LanguageStatusItem, StatusBarItem, Uri } from "vscode";
import { IServiceContainer } from "../../ioc/types";
import { IWorkspaceService } from "../../common/application/types";
import { IDisposableRegistry, IPathUtils, Resource } from "../../common/types";
import { EQEnvironment } from "../../eqEnvironments/info";
import { traceLog } from "../../logging";
import { InterpreterQuickPickList } from "../../common/utils/localize";

const localize: nls.LocalizeFunc = nls.loadMessageBundle();
const STATUS_BAR_ITEM_PRIORITY = 100.09999;
@injectable()
export class InterpreterDisplay implements IInterpreterDisplay, IExtensionSingleActivationService {
  public supportedWorkspaceTypes: { untrustedWorkspace: boolean; virtualWorkspace: boolean } = {
    untrustedWorkspace: false,
    virtualWorkspace: true,
  };
  private statusBar: StatusBarItem | undefined;
  private useLanguageStatus = false;
  private languageStatus: LanguageStatusItem | undefined;
  private readonly helper: IInterpreterHelper;
  private readonly workspaceService: IWorkspaceService;
  private readonly pathUtils: IPathUtils;
  private readonly interpreterService: IInterpreterService;
  private currentlySelectedInterpreterDisplay?: string;
  private currentlySelectedInterpreterPath?: string;
  private currentlySelectedWorkspaceFolder: Resource;
  private statusBarCanBeDisplayed?: boolean;
  private visibilityFilters: IInterpreterStatusbarVisibilityFilter[] = [];
  private disposableRegistry: Disposable[];

  constructor(@inject(IServiceContainer) private readonly serviceContainer: IServiceContainer) {
    this.helper = serviceContainer.get<IInterpreterHelper>(IInterpreterHelper);
    this.workspaceService = serviceContainer.get<IWorkspaceService>(IWorkspaceService);
    this.pathUtils = serviceContainer.get<IPathUtils>(IPathUtils);
    this.interpreterService = serviceContainer.get<IInterpreterService>(IInterpreterService);

    this.disposableRegistry = serviceContainer.get<Disposable[]>(IDisposableRegistry);

    this.interpreterService.onDidChangeInterpreterInformation(
      this.onDidChangeInterpreterInformation,
      this,
      this.disposableRegistry,
    );
  }

  activate(): Promise<void> {
    throw new Error("60Method not implemented.");
  }
  public async refresh(resource?: Uri) {
    // Use the workspace Uri if available
    if (resource && this.workspaceService.getWorkspaceFolder(resource)) {
        resource = this.workspaceService.getWorkspaceFolder(resource)!.uri;
    }
    if (!resource) {
        const wkspc = this.helper.getActiveWorkspaceUri(resource);
        resource = wkspc ? wkspc.folderUri : undefined;
    }
    await this.updateDisplay(resource);
}
  public registerVisibilityFilter(filter: IInterpreterStatusbarVisibilityFilter) {
    const disposableRegistry = this.serviceContainer.get<Disposable[]>(IDisposableRegistry);
    this.visibilityFilters.push(filter);
    if (filter.changed) {
        filter.changed(this.updateVisibility, this, disposableRegistry);
    }
}
  private onDidChangeInterpreterInformation(info: EQEnvironment) {
    if (!this.currentlySelectedInterpreterPath || this.currentlySelectedInterpreterPath === info.path) {
      this.updateDisplay(this.currentlySelectedWorkspaceFolder).ignoreErrors();
    }
  }
  private async updateDisplay(workspaceFolder?: Uri) {
    const interpreter = await this.interpreterService.getActiveInterpreter(workspaceFolder);
    if (
      this.currentlySelectedInterpreterDisplay &&
      this.currentlySelectedInterpreterDisplay === interpreter?.detailedDisplayName
    ) {
      return;
    }
    this.currentlySelectedWorkspaceFolder = workspaceFolder;
    if (this.statusBar) {
      if (interpreter) {
        this.statusBar.color = '';
        this.statusBar.tooltip = this.pathUtils.getDisplayName(interpreter.path, workspaceFolder?.fsPath);
        if (this.currentlySelectedInterpreterPath !== interpreter.path) {
          traceLog(
            localize(
              'Interpreters.statusBarEQInterpreterPath',
              'EQ interpreter path: {0}',
              this.pathUtils.getDisplayName(interpreter.path, workspaceFolder?.fsPath),
            ),
          );
          this.currentlySelectedInterpreterPath = interpreter.path;
        }
        let text = interpreter.detailedDisplayName;
        text = text?.startsWith('EQ') ? text?.substring('EQ'.length)?.trim() : text;
        this.statusBar.text = text ?? '';
        this.currentlySelectedInterpreterDisplay = interpreter.detailedDisplayName;
      } else {
        this.statusBar.tooltip = '';
        this.statusBar.color = '';
        this.statusBar.text = `$(alert) ${InterpreterQuickPickList.browsePath.openButtonLabel}`;
        this.currentlySelectedInterpreterDisplay = undefined;
      }
    } else if (this.languageStatus) {
      if (interpreter) {
        this.languageStatus.detail = this.pathUtils.getDisplayName(interpreter.path, workspaceFolder?.fsPath);
        if (this.currentlySelectedInterpreterPath !== interpreter.path) {
          traceLog(
            localize(
              'InterpreterseqInterpreterPath',
              'EQ interpreter path: {0}',
              this.pathUtils.getDisplayName(interpreter.path, workspaceFolder?.fsPath),
            ),
          );
          this.currentlySelectedInterpreterPath = interpreter.path;
        }
        let text = interpreter.detailedDisplayName!;
        text = text.startsWith('EQ') ? text.substring('EQ'.length).trim() : text;
        this.languageStatus.text = text;
        this.currentlySelectedInterpreterDisplay = interpreter.detailedDisplayName;
      } else {
        this.languageStatus.text = '$(alert) No Interpreter Selected';
        this.languageStatus.detail = undefined;
        this.currentlySelectedInterpreterDisplay = undefined;
      }
    }
    this.statusBarCanBeDisplayed = true;
    this.updateVisibility();
  }
  private updateVisibility() {
    if (!this.statusBar || !this.statusBarCanBeDisplayed) {
      return;
    }
    if (this.visibilityFilters.length === 0 || this.visibilityFilters.every((filter) => !filter.hidden)) {
      this.statusBar.show();
    } else {
      this.statusBar.hide();
    }
  }
}